#ifndef LUT_H
#define LUT_H

#include <vector>
#include "base/aig.h"
#include "cktsat/satsolver.h"

class Lit;
class CktName;
class StrashAIG;
namespace Minisat{ class Solver ;} 

typedef unsigned short fun_t;
typedef std::vector<uint8_t> pat_t;

struct LUT
{
   unsigned in[4];
   fun_t    init; 
   inline unsigned operator[](unsigned i)const{ return in[i];}
   inline unsigned & operator[](unsigned i){return in[i];}
   LUT(){}
};

struct FPGA : public std::vector< LUT > 
{
   unsigned         andFlag;
   std::vector<unsigned> po;
	unsigned 	*    focnt;
	unsigned    *    level;

   StrashAIG      * aig;
   AigLit         * mapping;
   
   // public function 
   void read_bench( const char * , CktName * = NULL );
   void write_bench( const char * , CktName * = NULL  )const;

   // run minato morrele algorithm and qfactor 
   void init();
   void report();

   FPGA():focnt(NULL),level(NULL),aig(NULL),mapping(NULL),plot_score(NULL){}
   ~FPGA(){ delete aig; delete [] mapping , delete [] focnt , delete [] level; if( plot_score ){ for( unsigned i = 0 ; i < size() ; ++ i )delete [] plot_score[i];} delete [] plot_score; }

	double ** plot_score;
	void init_plot( unsigned vs );
	void plot( const char * file , unsigned vs , std::vector<unsigned> & cand , std::vector<unsigned> & ans );
	void record_score( double * sc , unsigned k)
	{
		if( plot_score == NULL )return;
		for( unsigned i = 0 ; i < size() ; ++i ) plot_score[i][k] = sc[i];
	}
};

struct Parameter 
{
	static int PAT_SIM_CONF;
   static int PAT_SAT_CONF; // the sat base pattern generation conflict limit 

	static int SIM_SIZE;  // number of simulation pattern of bad pattern 
	static int SIM_GOOD_SIZE;	  // number of simulation pattern of good pattern
	static int SAT_PAT_OUT_SIZE;
	static int P_SEL_SAT_OUT;

	static int CAND_UBOUND;
	static int CAND_LBOUND;

   static double   CAND_SCORE;   // the threadhold of selecting candidate 
	static double   PUSH_TO_INPUT_FACTOR;
	static double   PUSH_TO_OUTPUT_FACTOR;
	static double 	 FILTER_FACTOR;

	static double 	 REFINE_FACTOR1;
	static double 	 REFINE_FACTOR2;
	static int 		 FIX_ALL;
	static int 		 SYN_BY_SAT_CONFLICT;

	static double 	 POS;
	static double 	 NEG;

	static void 	 change_cand1( int up );
	static void 	 change_cand2( int up );
	static void 	 change_pat( int up);
	static void 	 change();
};

#endif 
